/*
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

/*
 *
 *
 *
 *
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;

/**
 * 一个可以自动更新的int值。看java.util.concurrent.atomic包描述原子变量属性的规范。
 * AtomicInteger用于像原子递增计数器这样的应用程序，不能用作java.lang.Integer的替代品。
 * 然而，这个类确实扩展了Number，允许处理基于数字的类的工具和实用程序进行统一访问。
 *
 * @since 1.5
 * @author Doug Lea
*/
public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    // Unsafe构造器私有，且是一个单例模式，只能通过单例方法getUnsafe获得实例。可以使用指针偏移操作。
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    // value的偏移量，用于unsafe对这个对象的对应的偏移量进行操作
    private static final long valueOffset;

    static {
        try {
        	// 在静态初始化块中，通过反射的Field和Unsafe的objectFieldOffset，获得了value这个域相对于AtomicInteger对象的地址偏移量。
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    // value域，是AtomicInteger对象的数据来源。
    // 它被设置为volatile的，使得对value的操作结果都具有可见性。
    //（注意，不保证原子性，比如value++这样的复合操作）
    private volatile int value;

    /**
     * 使用给定的初始值创建一个新的AtomicInteger。
     *
     * @param initialValue the initial value
     */
    public AtomicInteger(int initialValue) {
        value = initialValue;
    }

    /**
     * 使用初始值0创建一个新的AtomicInteger。
     */
    public AtomicInteger() {
    }


    /**
     * 获取当前值。
     * 可见get/set没有加锁，但在多线程环境下，这两个函数也能保证线程安全。
     * 因为return操作和赋值操作都是原子操作，所以两个函数都有原子性了，且volatile的value又使得对value的操作结果都具有可见性。
     *
     * @return the current value
     */
    public final int get() {
        return value;
    }

    /**
     * 设置为给定值。
     *
     * @param newValue the new value
     */
    public final void set(int newValue) {
        value = newValue;
    }

    /**
     * 最终设置为给定的值。
     * 简单地说，lazySet使得程序执行变快了，但损失了可见性，
     * 可见性直到有某个volatile write操作或同步操作才能恢复。
     * volatile write操作会在该操作前添加 store-store内存屏障，在该操作之后添加 store-load内存屏障，但lazySet却省去了这个 store-load内存屏障。
     * 这样，lazySet操作不会与任何先前的写操作重新排序，但可以与后续操作重新排序
     * （lazySet操作因为重排序，可能排在了 它的后续操作的后面，自然也就不能保证其他线程可见了）。
     *
     * @param newValue the new value
     * @since 1.6
     */
    public final void lazySet(int newValue) {
        unsafe.putOrderedInt(this, valueOffset, newValue);
    }

    /**
     * 原子地设置给定值并返回旧值。
     * 
     *     	public final int getAndSetInt(Object o, long offset, int newValue) {
     *		      int v;
     *		      do {
     *		          v = getIntVolatile(o, offset);
     *		       } while (!compareAndSwapInt(o, offset, v, newValue));
     *		       return v;
     *		  }
     * 上来就直接调用了Unsafe的操作。Unsafe的getAndSetInt逻辑，利用了 循环和CAS操作（compareAndSwap）和volatile变量，
     * 使得更新操作不需要加锁就能完全，不过缺点是有可能会循环若干次才能成功。
     * getIntVolatile使得线程总是获得变量的最新更新的值。
     * 
     * compareAndSwapInt的前两个参数，根据指针o和指针偏移offset和int值所占字节数量4，可以读取出该对象中的value值是多少。
     * 如果通过指针偏移发现 对象的value值 和 expected相同，那么将 对象的value值 设为 x，并返回true；
     * 如果通过指针偏移发现 对象的value值 和 expected不相同，直接返回false。
     * 
     * 而循环配合compareAndSwapInt，则使得，只有当对象的value值 在v = getIntVolatile(o, offset)和
     * compareAndSwapInt(o, offset, v, newValue)的执行过程之间没有被其他线程修改的情况下
     * （有可能执行前者之后，线程就被切换出去了，然后线程重新开始执行时，值已经被修改了），才会设置新值成功。
     * 这个函数的缺点在于，有可能需要执行好多次循环，函数才能结束。
     *		    
     *
     * @param newValue the new value
     * @return the previous value
     */
    public final int getAndSet(int newValue) {
        return unsafe.getAndSetInt(this, valueOffset, newValue);
    }

    /**
     * 如果当前值==期望值，则自动将值设置为给定的更新值。
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
    	// compareAndSet函数相比上一个函数，没有循环了，粒度变小了。它只是让你执行一次CAS操作，结果成功或者失败。
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * 如果当前值==期望值，则自动将值设置为给定的更新值。
     *
     * <p>可能会错误地失败，并且不提供排序保证，所以它很少是compareAndSet的合适的替代品。
     * 
     * compareAndSet函数的weak版，但实现和compareAndSet一模一样，只能说，源码作者还没来得及写它的不同实现呢。
     * 它可能会返回 虚假的失败，且不提供排序保证。
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful
     */
    public final boolean weakCompareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

    /**
     * 将当前值原子地加1。
     * 
     * 这几个函数都调用unsafe.getAndAddInt。
     * 
     *     public final int getAndAddInt(Object o, long offset, int delta) {
     *         int v;
     *         do {
     *             v = getIntVolatile(o, offset);
     *         } while (!compareAndSwapInt(o, offset, v, v + delta));
     *         return v;
     *     }
     *  方法和getAndSetInt差不多，区别再去新的值不在固定，而是v+delta   
     * 
     * 区别在于：
     * getAndIncrement相当于i++，getAndAddInt刚好返回旧值。
     * getAndDecrement相当于i--。
     * getAndAdd相当于i += n，但是它却返回旧值。
     * 
     * incrementAndGet相当于++i，返回 getAndAddInt的旧值再加1.
     * decrementAndGet相当于--i，返回 getAndAddInt的旧值再减1.
     * addAndGet相当于i += n，返回 getAndAddInt的旧值再加n。
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }

    /**
     * 使当前值原子地递减一。
     *
     * @return the previous value
     */
    public final int getAndDecrement() {
        return unsafe.getAndAddInt(this, valueOffset, -1);
    }

    /**
     * 原子地将给定值添加到当前值。
     *
     * @param delta the value to add
     * @return the previous value
     */
    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

    /**
     * 将当前值原子地加1。
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
    	// 先得到原来的值，然后直接进行加减，然后返回
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

    /**
     * Atomically decrements by one the current value.
     *
     * @return the updated value
     */
    public final int decrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, -1) - 1;
    }

    /**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the updated value
     */
    public final int addAndGet(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta) + delta;
    }

    /**
     * 用应用给定函数的结果自动更新当前值，返回前一个值。
     * 这个函数应该是没有副作用的，因为当尝试的更新由于线程间的争用而失败时，它可能会被重新应用。
     * 
     * IntUnaryOperator是个函数式接口，看名字Unary就知道，它代表一个int的一元方程。
     * 如果当你需要根据旧值来更新新值，且需要将更新的逻辑包含在函数式接口中时，就需要使用该函数。
     * 注意，传入的IntUnaryOperator不应该有副作用，它应该只操作自己的局部变量。
     * updateAndGet与前者的区别在于，它返回新值。
     *
     * @param updateFunction a side-effect-free function
     * @return the previous value
     * @since 1.8
     */
    public final int getAndUpdate(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
        	// 先得到当前的值，然后用updateFunction计算结果
        	//然后判断当前值是否是prev，是的话，设置为next
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    /**
     * Atomically updates the current value with the results of
     * applying the given function, returning the updated value. The
     * function should be side-effect-free, since it may be re-applied
     * when attempted updates fail due to contention among threads.
     *
     * @param updateFunction a side-effect-free function
     * @return the updated value
     * @since 1.8
     */
    public final int updateAndGet(IntUnaryOperator updateFunction) {
        int prev, next;
        do {
            prev = get();
            next = updateFunction.applyAsInt(prev);
        } while (!compareAndSet(prev, next));
        return next;
    }

    /**
     * 将给定函数应用到当前值和给定值的结果自动更新当前值，并返回前一个值。
     * 这个函数应该是无效果的，因为当由于线程间的争用而导致竞争更新失败时，它可能会被重新应用。
     * 函数的第一个参数是当前值，第二个参数是给定的update。
     * 
     * IntBinaryOperator是int的二元方程，所以还需要一个参数x。
     *
     * @param x the update value
     * @param accumulatorFunction a side-effect-free function of two arguments
     * @return the previous value
     * @since 1.8
     */
    public final int getAndAccumulate(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return prev;
    }

    /**
     * Atomically updates the current value with the results of
     * applying the given function to the current and given values,
     * returning the updated value. The function should be
     * side-effect-free, since it may be re-applied when attempted
     * updates fail due to contention among threads.  The function
     * is applied with the current value as its first argument,
     * and the given update as the second argument.
     *
     * @param x the update value
     * @param accumulatorFunction a side-effect-free function of two arguments
     * @return the updated value
     * @since 1.8
     */
    public final int accumulateAndGet(int x,
                                      IntBinaryOperator accumulatorFunction) {
        int prev, next;
        do {
            prev = get();
            next = accumulatorFunction.applyAsInt(prev, x);
        } while (!compareAndSet(prev, next));
        return next;
    }

    /**
     * 返回当前值的字符串表示形式。
     * 
     * @return the String representation of the current value
     */
    public String toString() {
        return Integer.toString(get());
    }

    /**
     * 返回这个AtomicInteger的int值。
     */
    public int intValue() {
        return get();
    }

    /**
     * 返回该AtomicInteger的值作为扩展原语转换后的long值。
     * 
     * @jls 5.1.2 Widening Primitive Conversions
     */
    public long longValue() {
        return (long)get();
    }

    /**
     * Returns the value of this {@code AtomicInteger} as a {@code float}
     * after a widening primitive conversion.
     * @jls 5.1.2 Widening Primitive Conversions
     */
    public float floatValue() {
        return (float)get();
    }

    /**
     * Returns the value of this {@code AtomicInteger} as a {@code double}
     * after a widening primitive conversion.
     * @jls 5.1.2 Widening Primitive Conversions
     */
    public double doubleValue() {
        return (double)get();
    }

}
